import json
import os
import re
import shutil
import stat
from test_tools.script import debug_log

# patterns = [
#     re.compile(r"E/Unity"),  # 匹配 E/Unity
#     re.compile(r"E Unity\s+:")  # 匹配 E Unity + 任意空格 + :
# ]

log = debug_log.log


def check_str(s: any) -> bool:
    """
    检查输入是否为非空字符串且仅包含空格字符

    条件：
    1. 输入不能是 None
    2. 必须是字符串类型
    3. 不能是空字符串 ""
    4. 不能全部由空白字符组成（空格、制表符、换行等）

    :param s: 输入值
    :return: 是否满足条件
    """
    if s is None or not isinstance(s, str):
        return False
    return len(s) > 0 and not re.fullmatch(r'\s+', s) is not None


def validate_ip_port(s: str) -> bool:
    """
    校验字符串是否为合法 IPv4地址 + 端口格式

    条件：
    1. IPv4 必须符合 0.0.0.0 - 255.255.255.255
    2. 端口必须为 1-65535
    3. 不允许前导零（如 127.0.0.1:080 → 无效）
    """
    pattern = (r'^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d):([1-9]\d{0,3}|[1-5]\d{'
               r'4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')
    _result = re.sub(r'\s+', '', s)  # 正则匹配所有空白符
    return re.match(pattern, _result) is not None


def contains_keywords(_text: str, patterns: list) -> bool:
    """
    判断文本是否包含指定的任意一个关键字模式

    :param _text: 需要匹配的文本内容
    :param patterns: 正则表达式列表，每个元素是一个 re.compile 生成的正则表达式对象
    :return: 如果任意一个正则表达式匹配成功，则返回 True，否则返回 False
    """
    return any(pattern.search(_text) for pattern in patterns)


def get_json_data(path: str) -> dict:
    """
    获取指定路径的json数据

    Args:
        path (str): 指定的json文件路径

    Returns:
        json: 返回该文件的json数据
    """
    try:
        if check_json_path(path):
            with open(path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            return data
        else:
            return {}
    except Exception as e:
        raise f"未知错误：{e}"


def write_json_data(path: str, data) -> None:
    """将json数据写入指定文件"""
    try:
        if check_json_path(path):
            with open(path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=4)
    except Exception as e:
        raise f"未知错误：{e}"


def check_json_path(path: str) -> bool:
    """检查json文件"""
    if path == "":
        log(f"{path}路径错误,路径为空")
        return False
    if not os.path.exists(path):
        log(f"{path}路径错误,路径不存在")
        return False
    if not os.path.isfile(path):
        log(f"{path}路径错误,不是文件")
        return False
    if not path.endswith(".json"):
        log(f"{path}路径错误，不是json文件")
        return False
    return True


def load_file(path: str) -> str:
    """读取指定路径文件内容，如果文件无内容，然会空字符串"""
    try:
        with open(path, "r") as f:
            content = f.read().strip()
            if content:
                return content
            else:
                return ""
    except Exception as e:
        raise e


def read_lines_file(path: str) -> list:
    """按行读取文件，返回读取到的行列表"""
    try:
        temp = []
        with open(path, 'r', encoding='utf-8') as file:
            contents = file.readlines()
            for line in contents:
                temp.append(line.strip())
            return temp
    except Exception as e:
        raise e


def write_file(path: str, contents) -> None:
    """写入文件"""
    try:
        with open(path, 'w', encoding='utf-8') as file:
            file.write(contents)
    except Exception as e:
        raise e


def delete_file(path: str):
    """删除文件"""
    try:
        if os.path.exists(path):
            # 尝试删除文件
            os.remove(path)
    except Exception as e:
        # 处理其他可能的异常
        raise f"发生了一个错误: {e}"


def join_path(root, path):
    """将文件或文件夹和指定目录拼接，并返回组合后的绝对路径。

    Args:
        root (str): 需要拼接的目录。
        path (str): 文件或文件夹。

    Returns:
        str: 组合后的绝对路径。
    """
    return os.path.join(root, path).replace('\\', '/')


def add_path(root_path, path):
    """将路径和根目录组合起来，并返回组合后的路径。
    Args:
        root_path:根目录
        path (str): 目录或文件名。
    Returns:
        str: 和根目录组合后的路径。
    """
    # 如果是相对路径，则将其与根路径组合
    if not os.path.isabs(path):
        path = join_path(root_path, path)
    # 检查路径是否存在
    if os.path.exists(path):
        # log(f"路径 {path} 添加成功")
        return path
    else:
        # log(f"路径 {path} 不存在")
        return ""


def get_files_list(path):
    """获取指定文件夹中所有文件的路径

    Args:
        path (str): 目录名

    Returns:
        list: 返回文件路径列表
    """
    if os.path.isfile(path):
        path = os.path.dirname(path)
    files_list: list = []
    # 获取目录中所有文件和文件夹的名称
    for filename in os.listdir(path):
        # 使用 join 函数将目录路径和文件名拼接起来，形成完整路径
        file_path = join_path(path, filename)
        # 检查是否为文件，并打添加到列表中
        if os.path.isfile(file_path):
            files_list.append(file_path)
    return files_list


def clear_dir(dir_path, ignore='.zip'):
    """
    检查文件夹是否存在，存在则清除文件夹中的所有内容，不存在则创建,ignore参数为忽略删除的文件后缀，默认.zip格式不删除
    """
    log(f"ToolBox -> clear_dir")
    log(dir_path)
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)
        log(f"新建文件夹 {dir_path}")
    else:
        # 从底层子目录向上删除
        for root, dirs, files in os.walk(dir_path, topdown=False):
            for file in files:
                file_path = os.path.join(root, file)
                name, extension = os.path.splitext(file_path)
                if extension == ignore:
                    continue
                os.chmod(file_path, stat.S_IWRITE)  # 赋予用户写权限
                os.remove(file_path)  # 删除文件
                log(f"删除 ** {file_path} ** ")
            for dir_name in dirs:
                _path = os.path.join(root, dir_name)
                os.chmod(_path, stat.S_IWRITE)  # 赋予用户写权限
                os.rmdir(_path)  # 删除空子文件夹


def get_dir_list(path):
    """获取指定文件夹或文件所在文件夹中所有文件夹的路径

    Args:
        path (str): 目录名或文件名

    Returns:
        list: 返回文件夹绝对路径列表
    """
    if os.path.isfile(path):
        path = os.path.dirname(path)
    dir_list = []
    # 获取目录中所有文件和文件夹的名称
    for filename in os.listdir(path):
        # 使用 join 函数将目录路径和文件名拼接起来，形成完整路径
        dir_path = join_path(path, filename)
        # 检查是否为文件，并打添加到列表中
        if not os.path.isfile(dir_path):
            dir_list.append(dir_path)
    return dir_list


def get_files_json(path):
    """获取指定文件夹中所有文件的路径，并返回字典，key：文件名，value：文件路径

    Args:
        path (str): 指定文件夹路径

    Returns:
        dic: 文件夹中所有文件的路径字典
    """
    if os.path.isfile(path):
        path = os.path.dirname(path)
    files_dic = {}
    for filename in os.listdir(path):
        # 使用 join 函数将目录路径和文件名拼接起来，形成完整路径
        file_path = join_path(path, filename)
        # 检查是否为文件，并打添加到列表中
        if os.path.isfile(file_path):
            files_dic.setdefault(os.path.splitext(filename)[0], file_path)
    return files_dic


def get_dir_json(path):
    """获取指定文件夹或文件所在文件夹中所有文件夹的路径字典，key：文件夹名，value：文件夹绝对路径

    Args:
        path (str): 目录名或文件名

    Returns:
        list: 返回文件夹绝对路径字典
    """
    if os.path.isfile(path):
        path = os.path.dirname(path)
    dir_dic = {}
    # 获取目录中所有文件和文件夹的名称
    for filename in os.listdir(path):
        # 使用 join 函数将目录路径和文件名拼接起来，形成完整路径
        dir_path = join_path(path, filename)
        # 检查是否为文件，并打添加到列表中
        if not os.path.isfile(dir_path):
            dir_dic.setdefault(os.path.splitext(filename)[0], dir_path)
    return dir_dic

# if __name__ == '__main__':
# # 测试用例
# test_cases = [
#     (None, False),  # 非字符串 → 失败
#     ("", False),  # 空字符串 → 失败
#     ("   ", False),  # 纯空格 → 成功
#     ("\t\n", False),  # 含制表符/换行 → 成功
#     (" hello ", True),  # 含有效字符 → 失败
#     (123, False),  # 数字类型 → 失败
#     ([" "], False),  # 列表类型 → 失败
#     ("127.0.0.1:5555", True)
# ]
#
# for input_val, expected in test_cases:
#     result = check_str(input_val)
#     log(f"输入：{repr(input_val):<10} 预期：{expected} 实际：{result} → {'通过' if result == expected else '失败'}")
#
# log(validate_ip_port(" 127.0.0.1:5555"))  # True
# log(validate_ip_port("192. 168.1.1:8080"))  # True
# log(validate_ip_port("10.0.0.1:0a"))  # False
# log(validate_ip_port("256.1.1.1:80 a"))  # False

# with open("D:/data/dataTools/test/log.txt", 'r', encoding='utf-8') as f:
#     text = f.read()
#     texts = text.split("\n")
#     for text in texts:
#         log(contains_keywords(text))
